{
  DataAsMessage plugin for Miranda IM
  Copyright (c) 2006 Chervov Dmitry

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
}

{$IFNDEF M_DATAASMESSAGE}
{$DEFINE M_DATAASMESSAGE}

const
// DAM_SENDRESULTINFO::iResult values
  DAM_SR_SUCCESS         = 0;
  DAM_SR_TIMEOUT         = 1; // timeout period expired; this value is returned
                              // also if the contact went offline for a time
                              // longer than a timeout period
  DAM_SR_NOTSUPPORTED    = 2; // means this szDataType is not supported by the
                              // remote side
  DAM_SR_NODAM           = 3; // means there is no DataAsMessage plugin on the
                              // remote side; keep in mind that this error may
                              // also appear accidentally because of a bad
                              // connectivity during the handshake (if there
                              // was a timeout when waiting for a response)
  DAM_SR_CANCELLEDLOCAL  = 4; // cancelled from the local(sending) side
  DAM_SR_CANCELLEDREMOTE = 5; // cancelled from the remote(receiving) side
  DAM_SR_BADCRC          = 6; // bad CRC; we can't do anything with this error. presumably, it will happen rarely, and the most probable cause is the protocol that filters some of characters in our messages OR it may be a bug in DataAsMessage plugin (hopefully not ;) ).
  DAM_SR_UNKNOWN         = 7; // unknown error

// Return values for DAM_SENDRESULTPROC
   DAM_SRA_RETRY = 1;

type
// hContact, szDataType and SessionID fields correspond to the fields of the
// DAM_SENDDATAINFO structure
  PDAM_SENDRESULTINFO = ^TDAM_SENDRESULTINFO;
  TDAM_SENDRESULTINFO = record
    cbSize    :int; // sizeof(DAM_SENDRESULTINFO)
    hContact  :THANDLE;
    szDataType:PChar;
    SessionID :dword;
    iResult   :int; // transmission result code
  end; 

type
  TDAM_SENDRESULTPROC = function(sri:PDAM_SENDRESULTINFO):int; cdecl;
// this procedure receives the result of the transmission. it's called when the
// session closes (either the data was sent successfully or there was an error)
// you can return DAM_SRA_RETRY when iResult is DAM_SR_TIMEOUT if you want to
// retry sending

const
// DAM_SENDDATAINFO::Flags constants
  DAM_SDF_DONTPACK  = 1; // don't pack the data (by default all the data is packed)
  DAM_SDF_NOTIMEOUT = 2; // don't generate a timeout error ever, keep trying to
                         // send the data. If the contact is offline, the data
                         // is saved in the memory until the contact goes online.
                         // Loss of the data occurs only if the sender's miranda
                         // closes (this may change in future to allow fully
                         // functional offline sending that will guarantee the
                         // data to be sent in any case, but of course the
                         // sending starts only when the both contacts are
                         // online). other errors than the timeout error can be
                         // still generated though.

type
  TDAM_SENDDATAINFO = record
    cbSize    :int;     // sizeof(DAM_SENDDATAINFO)
    hContact  :THANDLE;
    szDataType:PChar;   // zero-terminated string, containing data type,
                        // preferably in format "YourPluginName" or
                        // "YourPluginName/Something" (make sure this string
                        // won't coincide by an accident with someone else's
                        // string!). you can identify your data by this ID later
    nDataLen  :int;     // keep in mind that if the length is too big (more than
                        // about 8 KB), it's more preferable to split your data
                        // into several chunks, as you won't be able to "pick
                        // up" your data at the other end until all the data is
                        // transferred
    cData     :PChar;
    Flags     :int;     // combination of the DAM_SDF_ constants
    SendAfterSessionID:dword; // may be NULL; otherwise it's guaranteed that the
                              // sending starts only after successful completion
                              // of SendAfterSessionID session
    SendResultProc:TDAM_SENDRESULTPROC; // pointer to a procedure that receives
                                        // the result; can be NULL
    SessionID :dword; // OUT; receives the session ID
  end;

const
// MS_DAM_SENDDATA return values
  DAM_SDA_NOERROR         = 0;
  DAM_SDA_NOTSUPPORTED    = -1; // contact's protocol doesn't support sending/
                                // receiving messages
  DAM_SDA_TOOMANYSESSIONS = -2; // too many sessions

// MS_DAM_SENDDATA
// sends the data
// wParam = (WPARAM)(DAM_SENDDATAINFO*)sdi;
// lParam = 0
// Returns 0 (DAM_SDA_NOERROR) and fills SessionID if the session was queued for sending successfully; returns one of the DAM_SDA_ values on failure
  MS_DAM_SENDDATA = 'DataAsMessage/SendData';

(*
function DAMSendData(hContact:THANDLE; szDataType:PChar; nDataLen:int;
         cData:PChar; Flags:int; SendAfterSessionID:dword;
         SendResultProc:TDAM_SENDRESULTPROC;pSessionID:pdword):int;
var
  sdi:TDAM_SENDDATAINFO;
begin
  FillChar(sdi,SizeOf(sdi),0);
  sdi.cbSize    :=SizeOf(sdi);
  sdi.hContact  :=hContact;
  sdi.szDataType:=szDataType;
  sdi.nDataLen  :=nDataLen;
  sdi.cData     :=cData;
  sdi.Flags     :=Flags;
  sdi.SendAfterSessionID:=SendAfterSessionID;
  sdi.SendResultProc    :=SendResultProc;
  Result:=CallService(MS_DAM_SENDDATA,dword(@sdi),0);
  if pSessionID<>nil then
  	pSessionID^:=sdi.SessionID;
end;
*)

type
  TDAM_RECVDATAINFO = record
    cbSize    :int; // sizeof(DAM_RECVDATAINFO)
    hContact  :THANDLE;
    szDataType:PChar;
    nDataLen  :int;
    cData     :PChar;
  end;

const
// ME_DAM_RECVDATA
// hook up to this event to check for incoming data
// make sure rdi->szDataType is yours before doing anything!
// The important thing here is that your plugin will receive TWO ME_DAM_RECVDATA notifications on every single MS_DAM_SENDDATA call from a remote side:
//   The first notification arrives when the remote side starts to transmit the data. In this case DAM_RECVDATAINFO::cData = NULL (and DAM_RECVDATAINFO::nDataLen = -1) as we didn't receive any data yet. Return 1 to indicate that your plugin recognized the DAM_RECVDATAINFO::szDataType, otherwise return 0. If there are no any plugin that recognized the data, DAM cancels the transfer and there won't be any second notification for it.
//   The second notification is when the data is transmitted successfully. nDataLen contains the usual data size and cData points to the data buffer. cData is guaranteed to be valid only during the ME_DAM_RECVDATA call. You must copy the data to your own plugin's memory if you need it later. again, return 1 to indicate that your plugin recognized the data, otherwise return 0
// wParam = (WPARAM)(DAM_RECVDATAINFO*)rdi;
// lParam = 0
  ME_DAM_RECVDATA = 'DataAsMessage/RecvData';

{$ENDIF}
